/**
 * 
 */
package messenger;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Hashtable;

/**
 * @author (Group 42) William Orem, Joseph Hamilton, Kevin Benik
 * 
 */
public class UserAccount extends Contact implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6484290705341220770L;
	private String password;
	private AccountType type;
	private ArrayList<Contact> contacts;
	private Hashtable<Contact, MessageLog> messages = new Hashtable<Contact, MessageLog>();
	private ArrayList<Message> tmpMessages = new ArrayList<Message>();
	private boolean LoggedIn = false;
	Hashtable<Contact, ArrayList<ListCategory>> category = new Hashtable<Contact, ArrayList<ListCategory>>();

	/**
	 * 
	 * @param userName
	 * @param password
	 */
	public UserAccount(String userName, String password) {
		this.contacts = new ArrayList<Contact>();
		this.userName = userName;

		try {
			this.password = Security.getSaltedHash(password);
			ObjectInputStream inStream = new ObjectInputStream(
					new FileInputStream(userName + ".data"));
			readObject(inStream);
			inStream.close();
		} catch (FileNotFoundException e) {
			// if file not there no saved user
			this.LoggedIn = true;
		} catch (IOException e) {
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		try {
			if (Security.check(password, this.password))
				this.LoggedIn = true;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// this.LoggedIn=true;
	}
	
	/**
	 * 
	 */
	public UserAccount() {
	}

	/**
	 * @param friend
	 * @param sList
	 */
	public void addTOList(Contact friend, ListCategory sList) {
		if (!category.containsKey(friend)) {
			category.put(friend, new ArrayList<ListCategory>());
		}
		if (!category.get(friend).contains(sList))
			category.get(friend).add(sList);
	}

	/**
	 * @param username
	 * @return
	 */
	public Contact findContact(String username) {
		for (Contact u : contacts)
			if (u.getUserName().equalsIgnoreCase(username))
				return u;
		return null;

	}

	/**
	 * @return the contacts
	 */
	public ArrayList<Contact> getContacts() {
		return contacts;
	}

	/**
	 * @return a list of contact names for display with legend
	 */
	public ArrayList<String> getFriends() {
		ArrayList<String> temp = new ArrayList<String>();
		StringBuilder st = new StringBuilder();
		st.append("     \t "+"F I C F S J S\n"
				 +"     \t "+"a n o r o u e\n"
				 +"     \t "+"v s u e p n n\n"
				 +"     \t "+"o t r s h i i\n"
				 +"     \t "+"r r s h m o o\n"
				 +"     \t "+"i u e m o r r\n"
				 +"     \t "+"t c   a r    \n"
				 +"     \t "+"e t   n e    \n");
		temp.add(st.toString());
		for (int i = 0; i < contacts.size(); ++i)
			if (category.containsKey(contacts.get(i))){
				st = new StringBuilder();
				st.append("("+i+") \t");
				ArrayList<ListCategory> c = category.get((contacts.get(i)));
				if(c.contains(ListCategory.FAVORITE)) st.append("[* ");
				else st.append("[  ");
				if(c.contains(ListCategory.INSTRUCTOR)) st.append("I ");
				else st.append("  ");
				if(c.contains(ListCategory.COURSE)) st.append("C ");
				else st.append("  ");
				if(c.contains(ListCategory.FRESMAN)) st.append("F ");
				else st.append("  ");
				if(c.contains(ListCategory.SOPHMORE)) st.append("P ");
				else st.append("  ");
				if(c.contains(ListCategory.JUNIOR)) st.append("J ");
				else st.append("  ");
				if(c.contains(ListCategory.SENIOR)) st.append("S]   ");
				else st.append(" ]   ");
				st.append(contacts.get(i).getUserName());
				temp.add(st.toString());
			}else{
				st = new StringBuilder();
				st.append("("+i+") \t");
				st.append("[             ]   "+ contacts.get(i).getUserName());
				temp.add(st.toString());
			}
		return temp;
	}

	/**
	 * @return the messages
	 */
	public Hashtable<Contact, MessageLog> getMessages() {
		return messages;
	}


	/**
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * @return the tmpMessages
	 */
	public ArrayList<Message> getTmpMessages() {
		return tmpMessages;
	}

	/**
	 * @return the type
	 */
	public AccountType getType() {
		return type;
	}

	/**
	 * @return the userName
	 */
	public String getUserName() {
		return userName;
	}

	/**
	 * @return the loggedIn
	 */
	public boolean isLoggedIn() {
		return LoggedIn;
	}

	/**
	 * 
	 * @param inputStream
	 * @throws IOException
	 */
	@SuppressWarnings("unchecked")
	public void readObject(ObjectInputStream inputStream) throws IOException {
		try {
			this.userName = (String) inputStream.readObject();
			this.password = (String) inputStream.readObject();
			this.type = (AccountType) inputStream.readObject();
			this.pId = (String) inputStream.readObject();
			this.firstName = (String) inputStream.readObject();
			this.lastName = (String) inputStream.readObject();
			this.phone = (String) inputStream.readObject();
			this.eMail = (String) inputStream.readObject();
			this.year = inputStream.readInt();
			this.contacts = (ArrayList<Contact>) inputStream.readObject();
			this.category = (Hashtable<Contact, ArrayList<ListCategory>>) inputStream
					.readObject();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @return true is save successful
	 * 			saves the user & contactlist
	 */
	public boolean saveState() {
		try {
			ObjectOutputStream outStream = new ObjectOutputStream(
					new FileOutputStream(this.userName + ".data"));
			writeObject(outStream);
			// log.writeObject(outStream);
			outStream.close();
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} 

	}

	/**
	 * @param contacts
	 *            the contacts to set
	 */
	public void setContacts(ArrayList<Contact> contacts) {
		this.contacts = contacts;
	}

	/**
	 * @param loggedIn
	 *            the loggedIn to set
	 */
	public void setLoggedIn(boolean loggedIn) {
		LoggedIn = loggedIn;
	}

	/**
	 * @param messages
	 *            the messages to set
	 */
	public void setMessages(Hashtable<Contact, MessageLog> messages) {
		this.messages = messages;
	}

	/**
	 * @param password
	 *            the password to set
	 */
	public void setPassword(String password) {
		try {
			this.password = Security.getSaltedHash(password);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @param tmpMessages
	 *            the tmpMessages to set
	 */
	public void setTmpMessages(ArrayList<Message> tmpMessages) {
		this.tmpMessages = tmpMessages;
	}

	/**
	 * @param type
	 *            the type to set
	 */
	public void setType(AccountType type) {
		this.type = type;
	}

	/**
	 * @param userName
	 *            the userName to set
	 */
	public void setUserName(String userName) {
		this.userName = userName;
	}

	
	/**
	 * @param u
	 * 		the username of the user to delete
	 */
	public void deleteContact(String u) {
		getContacts().remove(findContact(u));

	}
	/**
	 * 
	 * @param outputStream
	 * @throws IOException
	 */
	public void writeObject(ObjectOutputStream outputStream) throws IOException {
		outputStream.writeObject(userName);
		outputStream.writeObject(password);
		outputStream.writeObject(type);
		outputStream.writeObject(pId);
		outputStream.writeObject(firstName);
		outputStream.writeObject(lastName);
		outputStream.writeObject(eMail);
		outputStream.writeObject(phone);
		outputStream.writeInt(year);
		outputStream.writeObject(contacts);
		outputStream.writeObject(category);
	}
}
